package com.flying.invest.strategy.service;

import java.text.DecimalFormat;
import java.util.Date;
import java.util.List;

import com.flying.common.annotation.DaoCreate;
import com.flying.common.annotation.DaoQuery;
import com.flying.common.annotation.DaoRemove;
import com.flying.common.annotation.DaoUpdate;
import com.flying.common.util.Codes;
import com.flying.common.util.DateUtils;
import com.flying.common.util.DateUtils.Field;
import com.flying.common.util.Utils;
import com.flying.framework.annotation.MethodInfo;
import com.flying.framework.annotation.Param;
import com.flying.framework.annotation.Service;
import com.flying.framework.exception.AppException;
import com.flying.framework.model.ActionResult;
import com.flying.framework.model.ModelFactory;
import com.flying.framework.model.QueryResult;
import com.flying.framework.service.AbstractService;
import com.flying.invest.assets.model.AssetsPrice;
import com.flying.invest.assets.service.AssetsPriceService;
import com.flying.invest.invest.TransactionType;
import com.flying.invest.invest.model.Investment;
import com.flying.invest.invest.service.InvestmentService;
import com.flying.invest.invest.service.InvestmentSuggestionService;
import com.flying.invest.strategy.model.Strategy;
import com.flying.invest.strategy.model.StrategyPriceChange;
import com.flying.invest.strategy.vo.PriceChangeDetail;

@Service(value="StrategyPriceChangeService", desc="价格变化监控策略")
public class StrategyPriceChangeService extends AbstractService implements IStrategyService{
    private InvestmentService investService;
    private StrategyService strategyService;
    private InvestmentSuggestionService suggestionService;
    private AssetsPriceService priceService;
    
    public void setInvestmentService(InvestmentService s) {
    	this.investService = s;
    }
    public void setStrategyService(StrategyService s) {
    	this.strategyService = s;
    }
    public void setInvestmentSuggestionService(InvestmentSuggestionService s) {
    	this.suggestionService = s;
    }
    public void setAssetsPriceService(AssetsPriceService s) {
    	this.priceService = s;
    }
        
	@MethodInfo("新增")
	@DaoCreate(entity=StrategyPriceChange.ENTITY_NAME)
	public StrategyPriceChange create(
		
			@Param(value=StrategyPriceChange.STRATEGY_ID, required=true,	desc="策略ID") Long strategy_id,
			@Param(value=StrategyPriceChange.FROM_DATE, required=true,	desc="开始日期") Date from_date,
			@Param(value=StrategyPriceChange.TO_DATE, required=false,	desc="结束日期") Date to_date,
			@Param(value=StrategyPriceChange.PRICE_BENCHMARK, required=true,	desc="基准价格") Double priceBenchmark,
			@Param(value=StrategyPriceChange.RISE_RATE, required=false,	desc="上涨比例") Double rise_rate,
			@Param(value=StrategyPriceChange.FELL_RATE, required=false,	desc="下跌比例") Double fell_rate
		
		) {
		
		return null;
	}

	@SuppressWarnings("unchecked")
	@Override
	public StrategyPriceChange createSub(Long strategy_id) {
		var strategy = this.strategyService.findById(strategy_id);
		var invest = this.investService.findById(strategy.getInvestId());
		Date from = DateUtils.add(new Date(), Field.MINUTE, -1);
		return this.create(strategy_id, from, null, invest.getPrice(), 0.15, 0.15);
	}

	@MethodInfo("修改")
	@DaoUpdate(entity=StrategyPriceChange.ENTITY_NAME)
	public ActionResult update(
		
			@Param(value=StrategyPriceChange.STRATEGY_ID, required=true,	desc="策略ID") Long strategy_id,
			@Param(value=StrategyPriceChange.FROM_DATE, required=true,	desc="开始日期") Date from_date,
			@Param(value=StrategyPriceChange.TO_DATE, required=false,	desc="结束日期") Date to_date,
			@Param(value=StrategyPriceChange.PRICE_BENCHMARK, required=true,	desc="基准价格") Double priceBenchmark,
			@Param(value=StrategyPriceChange.RISE_RATE, required=false,	desc="上涨比例") Double rise_rate,
			@Param(value=StrategyPriceChange.FELL_RATE, required=false,	desc="下跌比例") Double fell_rate
			
		) {
		
		return null;
	}
	
	public ActionResult config(
			@Param(value=StrategyPriceChange.STRATEGY_ID, required=true,	desc="策略ID") Long strategy_id,
			@Param(value=StrategyPriceChange.FROM_DATE, required=true,	desc="开始日期") Date from_date,
			@Param(value=StrategyPriceChange.TO_DATE, required=false,	desc="结束日期") Date to_date,
			@Param(value=StrategyPriceChange.PRICE_BENCHMARK, required=true,	desc="基准价格") Double priceBenchmark,
			@Param(value=StrategyPriceChange.RISE_RATE, required=false,	desc="上涨比例") Double rise_rate,
			@Param(value=StrategyPriceChange.FELL_RATE, required=false,	desc="下跌比例") Double fell_rate
			
		) {
		if(rise_rate == null && fell_rate == null ) {
			throw new AppException("0101", "上涨比例和下跌比例不能同时空！");
		}
		try {
			this.update(strategy_id, from_date, to_date, priceBenchmark, rise_rate, fell_rate);
		} catch (Exception e) {
			this.create(strategy_id, from_date, to_date, priceBenchmark, rise_rate, fell_rate);
		}
		this.flushDetails(strategy_id);
		return ModelFactory.create(ActionResult.class, Codes.CODE, Codes.SUCCESS);
	}

	@MethodInfo("删除")
	@DaoRemove(entity=StrategyPriceChange.ENTITY_NAME)
	public ActionResult remove(
		
			@Param(value=StrategyPriceChange.STRATEGY_ID, required=true,	desc="策略ID") Long strategy_id
		
		) {
		
		return null;
	}

	@MethodInfo("搜索")
	@DaoQuery(entity=StrategyPriceChange.ENTITY_NAME, pageable=true, modelClass=StrategyPriceChange.class)
	public QueryResult<StrategyPriceChange> findAll(
			@Param(value=Codes.PAGE_NUM, 	required=false, desc="分页页号，默认0") int page,
			@Param(value=Codes.PAGE_SIZE, 	required=false, desc="分页大小，默认10") int rows) {
		return null;
	}

	@SuppressWarnings("unchecked")
	@MethodInfo("查询")
	@DaoQuery(entity=StrategyPriceChange.ENTITY_NAME, single=true, throwsNotFoundException=true )
	public StrategyPriceChange findById(
			@Param(value=StrategyPriceChange.STRATEGY_ID, required=true,	desc="策略ID") Long strategy_id
		) {
		return null;
	}

	@Override
	public ActionResult executeStrategy(Long strategy_id) {
		Strategy strategy = this.strategyService.findById(strategy_id);
		Integer batch_num = strategy.getBatchNum() == null?0:strategy.getBatchNum();
		Investment v = this.investService.findById(strategy.getInvestId());
		StrategyPriceChange change = this.findById(strategy_id);
		AssetsPrice price = this.priceService.findTopPriceByAssetsId(v.getAssetsId(), 
				change.getFromDate(), change.getToDate() == null?new Date(): change.getToDate());
		
		Double current = v.getPrice();
		if(change.getRiseRate() != null && change.getRiseRate() > 0) {
			Double min = price.getMinPrice();
			Double rate = (current - min) / min;
			if(rate >= change.getRiseRate()) {
				String remarks = "当前价格"+v.getPrice()+"，相对于最低价格"+min+"已经上升了"+new DecimalFormat("#.##%").format(rate)+
						"，满足价格上涨监控"+ new DecimalFormat("#.##%").format(change.getRiseRate())+"卖出设定，建议卖出！";
				this.suggestionService.create(v.getUserId(), v.getInvestId(), strategy_id, batch_num+1, v.getAssetsName(), remarks, null,
						TransactionType.SELL.value(), 0.0, 0.0, null, null, null, "system", new Date());
			}
			
		} else if(change.getFellRate() != null && change.getFellRate() > 0) {
			Double max = price.getMaxPrice();
			Double rate = (max - current) / max;
			if(rate >= change.getFellRate()) {
				String remarks = "当前价格"+v.getPrice()+"，相对于最高价格"+max+"已经下跌了"+new DecimalFormat("#.##%").format(rate)+
						"，满足价格下跌监控"+ new DecimalFormat("#.##%").format(change.getFellRate())+"买入设定，建议买入！";
				this.suggestionService.create(v.getUserId(), v.getInvestId(), strategy_id, batch_num+1, v.getAssetsName(), remarks, null,
						TransactionType.BUY.value(), 0.0, 0.0, null, null, null, "system", new Date());
			}
		}
		return ModelFactory.create(ActionResult.class, Codes.CODE, Codes.SUCCESS);
	}

	@Override
	public ActionResult flushDetails(Long strategy_id) {
		return ModelFactory.create(ActionResult.class, Codes.CODE, Codes.SUCCESS);
	}
	
	@SuppressWarnings("unchecked")
	public QueryResult<PriceChangeDetail> findPriceChangeInfo(
			@Param(value=StrategyPriceChange.STRATEGY_ID, required=true,	desc="策略ID") Long strategy_id) {
		Strategy strategy = this.strategyService.findById(strategy_id);
		Investment v = this.investService.findById(strategy.getInvestId());
		StrategyPriceChange change = this.findById(strategy_id);
		
		Double price = v.getPrice();
		PriceChangeDetail min = new PriceChangeDetail(change.getPriceBenchmark(), change.getRiseRate(), change.getFellRate(), price);
		List<PriceChangeDetail> rows = Utils.newArrayList();
		rows.add(min);
		return ModelFactory.create(QueryResult.class, Codes.ROWS, rows);
	}
}